package com.user.query.pay.service.impl;


import com.hyrt.yzzd.weixin.config.WxPayConfig;
import com.hyrt.yzzd.weixin.util.PayCommonUtil;
import com.hyrt.yzzd.weixin.util.UnifyOrder;
import com.hyrt.yzzd.weixin.util.XMLUtil;
import com.user.query.pay.service.PayInfoService;
import com.user.query.pay.utils.ImageUtils;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.net.ssl.SSLContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.security.KeyStore;
import java.text.SimpleDateFormat;
import java.util.*;



@Service
public class PayInfoServiceImpl implements PayInfoService {
    Logger log = Logger.getLogger(PayInfoServiceImpl.class);
    @Value("#{wx['appid']}")
    private String appid;
    @Value("#{wx['mch_id']}")
    private String mch_id;
    @Value("#{wx['api_key']}")
    private String api_key;
    @Value("#{wx['spbill_create_ip']}")
    private String spbill_create_ip;
    @Value("#{wx['notify_url']}")
    private String notify_url;



	@Override
	public String wxtk(String orderId) {
		try {

		}catch (Exception e){
			throw  new RuntimeException();
		}
		return null;
	}

	@Override
	public String wxpay(String orderId) {
		// TODO 微信支付
		String imgPath = null;
			try{
				UnifyOrder qo = new UnifyOrder();
				String order_price = "1111";
				Map<String,String> params = new HashMap<String,String>();
				params.put("appid", appid);
				params.put("mch_id", mch_id);
				params.put("api_key", api_key);
				params.put("body", "医优堂订单");
				params.put("order_price", order_price);
				params.put("out_trade_no", "124545788878");//订单id
				params.put("spbill_create_ip", spbill_create_ip);
				params.put("notify_url", notify_url);
				params.put("trade_type", "NATIVE");
				Map<String,String> result = qo.sendUnify(params);
				Map<String,String> map1 = result;
			      for (Map.Entry<String, String> entry : map1.entrySet()) {  
			          System.out.println("键： " + entry.getKey() + " 值：" + entry.getValue());  
			      }  
			    String returnUrl = result.get("code_url");
			    System.out.println("===========code_url:"+returnUrl);
				if(StringUtils.isNotBlank(returnUrl)){
					SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
					String fileName = "WX"+sdf.format(new Date())+".jpg";
				    imgPath = ImageUtils.createWXImage(returnUrl, fileName);
				}else{
					log.info("微信支付（统一下单）失败，详细信息：return_code<"+result.get("return_code")+">   return_msg<"+result.get("return_msg")+">");
					imgPath = "1";
				}
			}catch(Exception e){
				log.error("微信获取支付二维码出错！", e);
			}
		return imgPath;
	}

	@Override
	public int verify(String orderId) {
		// TODO 是否支付成功

		return 0;
	}

	/*@Override
	public int verify2(OrderForm order) {
		addDival(order);
		return 0;
	}
*/
	@Override
	public void wxnotify(HttpServletRequest request, HttpServletResponse response) {
		String resXml = "";
		BufferedOutputStream out =null;
		// TODO 微信回调 异步通知
		try{
			out= new BufferedOutputStream(
					response.getOutputStream());
			//读取参数  
		    InputStream inputStream ;  
		    StringBuffer sb = new StringBuffer();  
		    inputStream = request.getInputStream();  
		    String s ;  
		    BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));  
		    while ((s = in.readLine()) != null){  
		        sb.append(s);  
		    }  
		    in.close();  
		    inputStream.close();  
		  
		    //解析xml成map  
		    Map<String, String> m = new HashMap<String, String>();  
		    m = XMLUtil.doXMLParse(sb.toString());
		      
		    //过滤空 设置 TreeMap
		    SortedMap<Object,Object> packageParams = new TreeMap<Object,Object>();
		    Iterator it = m.keySet().iterator();
		    while (it.hasNext()) {
		        String parameter = (String) it.next();
		        String parameterValue = m.get(parameter);

		        String v = "";
		        if(null != parameterValue) {
		            v = parameterValue.trim();
		        }
		        packageParams.put(parameter, v);
		    }

		    // 账号信息
		    String key =api_key; // api_key

		    //判断签名是否正确
		    if(PayCommonUtil.isTenpaySign("UTF-8", packageParams,key)) {
		    	//处理业务开始

	            if("SUCCESS".equals((String)packageParams.get("result_code"))){
	                // 支付成功
	            	String out_trade_no = (String)packageParams.get("out_trade_no");

	            	//判定订单是否已经被支付，不可重复支付
	            	if(true){
	            		resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
		                        + "<return_msg><![CDATA[已支付]]></return_msg>" + "</xml> ";
	            	}else if(false){
		                String transaction_id = (String)packageParams.get("transaction_id");
		                String total_fee = (String)packageParams.get("total_fee");//单位：分
		                //查询数据库中订单，首先判定订单中金额与返回的金额是否相等，不等金额被纂改
		                if(true){
		                	resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
			                        + "<return_msg><![CDATA[参数格式校验错误]]></return_msg>" + "</xml> ";
		                }else{
		                	//业务操作

							//通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.
			                resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"  
			                        + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> "; 
		                }
		                
	            	  }
		            } else {  
		                log.info("支付失败,错误信息：" + packageParams.get("err_code"));  
		                resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"  
		                        + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";  
		            }  

		            out.write(resXml.getBytes());  
		            out.flush();  
		            out.close();  
		    }
		}catch(Exception e){
			try{
			System.out.println("通知签名验证失败---时间::::"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
			log.error("微信回调出错",e);
			resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
					+ "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
			out.write(resXml.getBytes());
			out.flush();
			out.close();
			}catch(Exception e2){
				log.error("微信回调出错",e2);
				throw  new RuntimeException("回滚事物");
			}
			throw  new RuntimeException("回滚事物");
		}
    }



	public static Object refund(){
		System.out.println("==========================微信退款开始!!========================");
		try{
			KeyStore keyStore = KeyStore.getInstance("PKCS12");
			FileInputStream instream = new FileInputStream(new File("E:/cert/112.p12"));
			try {
				keyStore.load(instream,"1375567402".toCharArray());
			}finally {
				instream.close();
			}

			// Trust own CA and all self-signed certs
			SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore,
					"1375567402".toCharArray()).build();
			// Allow TLSv1 protocol only
			SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
					sslcontext, new String[] { "TLSv1" }, null,
					SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
			CloseableHttpClient httpclient = HttpClients.custom()
					.setSSLSocketFactory(sslsf).build();
			// HttpGet httpget = new
			// HttpGet("https://api.mch.weixin.qq.com/secapi/pay/refund");
			HttpPost httppost = new HttpPost(
					"https://api.mch.weixin.qq.com/secapi/pay/refund");

			// 账号信息
			String appid = WxPayConfig.APP_ID;  // appid
			//String appsecret = PayConfigUtil.APP_SECRET; // appsecret
			String mch_id = WxPayConfig.MCH_ID; // 商业号
			String key = WxPayConfig.API_KEY; // key

			String currTime = PayCommonUtil.getCurrTime();
			String strTime = currTime.substring(8, currTime.length());
			String strRandom = PayCommonUtil.buildRandom(4) + "";
			String nonce_str = strTime + strRandom;  //随机字符

			String total_fee = "1"; // 价格   注意：价格的单位是分
			String refund_fee = "1";
			String op_user_id = WxPayConfig.MCH_ID;   // 商品名称  goodsss
			String out_trade_no = "6917"; // 订单号
			String out_refund_no = PayCommonUtil.buildRandom(4) + "a";

			// 获取发起电脑 ip
			String spbill_create_ip = WxPayConfig.CREATE_IP;
			// 回调接口
			String notify_url = WxPayConfig.NOTIFY_URL;
			String trade_type = "NATIVE";

			SortedMap<Object,Object> packageParams = new TreeMap<Object,Object>();
			packageParams.put("appid", appid);
			packageParams.put("mch_id", mch_id);
			packageParams.put("nonce_str", nonce_str);
			packageParams.put("out_trade_no", out_trade_no);
			packageParams.put("out_refund_no", out_refund_no);
			packageParams.put("total_fee", total_fee);
			packageParams.put("refund_fee", refund_fee);
			packageParams.put("op_user_id", op_user_id);

			String sign = PayCommonUtil.createSign("UTF-8", packageParams,key);
			packageParams.put("sign", sign);

			String requestXML = PayCommonUtil.getRequestXml(packageParams);
			System.out.println(requestXML);
			//String resXml = HttpUtil.postData(WxPayConfig.REFUND_URL, requestXML);

                /*
                Map map = XMLUtil.doXMLParse(resXml);
                //String return_code = (String) map.get("return_code");
                //String prepay_id = (String) map.get("prepay_id");
                String return_code = (String) map.get("return_code");
                System.out.println("当前return_code："+return_code);
                String result_code = (String) map.get("result_code");
                System.out.println("当前result_code："+result_code);*/

			//String resXml = HttpUtil.postData(WxPayConfig.UFDODER_URL, requestXML);

			try {

				StringEntity se = new StringEntity(requestXML);

				httppost.setEntity(se);

				System.out.println("executing request" + httppost.getRequestLine());

				CloseableHttpResponse responseEntry = httpclient.execute(httppost);
				try {
					HttpEntity entity = responseEntry.getEntity();

					System.out.println("----------------------------------------");
					System.out.println(responseEntry.getStatusLine());
					if (entity != null) {
						System.out.println("Response content length: " + entity.getContentLength());

						SAXReader saxReader = new SAXReader();
						Document document = saxReader.read(entity.getContent());
						Element rootElt = document.getRootElement();
						System.out.println("根节点：" + rootElt.getName());
						System.out.println("==="+rootElt.elementText("return_code"));
						System.out.println("==="+rootElt.elementText("result_code"));
						System.out.println("==="+rootElt.elementText("transaction_id"));
						System.out.println("==="+rootElt.elementText("out_trade_no"));
						System.out.println("==="+rootElt.elementText("out_refund_no"));
						System.out.println("==="+rootElt.elementText("refund_id"));
						System.out.println("==="+rootElt.elementText("refund_channel"));
						System.out.println("==="+rootElt.elementText("refund_fee"));
						System.out.println("==="+rootElt.elementText("coupon_refund_fee"));
						String returnCode = rootElt.elementText("return_code");
						JSONObject result = new JSONObject();
						if(returnCode.equals("SUCCESS")){

							System.out.println("======================微信退款成功=================");

							result.put("status","success");
							result.put("msg","success");
							result.put("returnChannelType", rootElt.elementText("refund_channel"));
							result.put("otherRefundId", rootElt.elementText("out_refund_no"));
							//result.put("returnMoneyBak", Float.parseFloat(totalFee)/100);
							//result.put("returnMoneyBalance",(Float.parseFloat(totalFee)-Float.parseFloat(rootElt.elementText("refund_fee")))/100);
							result.put("returnOrderNo", rootElt.elementText("out_refund_no"));
						}else{
							result.put("status","false");
							result.put("msg",rootElt.elementText("err_code_des"));
						}


						return result;

					}
					EntityUtils.consume(entity);
				}
				finally {
					responseEntry.close();
				}
			}
			finally {
				httpclient.close();
			}
			return null;

		}catch(Exception e){
			e.printStackTrace();
			JSONObject result = new JSONObject();
			result.put("status","error");
			result.put("msg",e.getMessage());
			return result;
		}
	}

}
